iT邦幫忙

2024 iThome 鐵人賽

DAY 13
0
Software Development

數位醫療與雲原生第一次的親密接觸系列 第 13

Day 13 [數位醫療] 從零開始手搓multi-frame dicom

  • 分享至 

  • xImage
  •  

上一篇介紹了如何從Multi-frame Dicom取出圖片,今天要來跟大家分享如何用圖片合成出dicom檔。

首先一樣需要import一些dependency


<!--        &lt;!&ndash; https://mvnrepository.com/artifact/dcm4che/dcm4che &ndash;&gt;-->
      <dependency>
          <groupId>dcm4che</groupId>
          <artifactId>dcm4che</artifactId>
          <version>2.0.29</version>
          <type>pom</type>
      </dependency>

      <!-- https://mvnrepository.com/artifact/org.dcm4che/dcm4che-core -->
      <dependency>
          <groupId>org.dcm4che</groupId>
          <artifactId>dcm4che-core</artifactId>
          <version>5.22.4</version>
          <exclusions>
              <exclusion>
                  <artifactId>slf4j-log4j12</artifactId>
                  <groupId>org.slf4j</groupId>
              </exclusion>
          </exclusions>
      </dependency>

      <!-- https://mvnrepository.com/artifact/org.dcm4che/dcm4che-imageio -->
      <dependency>
          <groupId>org.dcm4che</groupId>
          <artifactId>dcm4che-imageio</artifactId>
          <version>5.22.4</version>
      </dependency>

      <!-- https://mvnrepository.com/artifact/org.dcm4che.tool/dcm4che-tool-common -->
      <dependency>
          <groupId>org.dcm4che.tool</groupId>
          <artifactId>dcm4che-tool-common</artifactId>
          <version>5.22.4</version>
      </dependency>
      <!-- https://mvnrepository.com/artifact/commons-cli/commons-cli -->
      <dependency>
          <groupId>commons-cli</groupId>
          <artifactId>commons-cli</artifactId>
          <version>1.4</version>
      </dependency>


      <!-- https://mvnrepository.com/artifact/org.dcm4che/dcm4che-image -->
      <dependency>
          <groupId>org.dcm4che</groupId>
          <artifactId>dcm4che-image</artifactId>
          <version>5.22.4</version>
          <exclusions>
              <exclusion>
                  <artifactId>slf4j-log4j12</artifactId>
                  <groupId>org.slf4j</groupId>
              </exclusion>
          </exclusions>
      </dependency>

      <dependency>
          <groupId>org.dcm4che</groupId>
          <artifactId>dcm4che-imageio-opencv</artifactId>
          <version>5.22.4</version>
      </dependency>

      <dependency>
          <groupId>org.dcm4che</groupId>
          <artifactId>dcm4che-imageio-rle</artifactId>
          <version>5.22.4</version>
          <scope>runtime</scope>
      </dependency>
>

      <!-- https://mvnrepository.com/artifact/org.dcm4che/dcm4che-json -->
      <dependency>
          <groupId>org.dcm4che</groupId>
          <artifactId>dcm4che-json</artifactId>
          <version>5.22.4</version>
      </dependency>

範例程式如下


    public static void main(String[] args) throws Exception {
        
         int BUFFER_SIZE = 8162;

    byte[] buf = new byte[BUFFER_SIZE];
        
        ElementDictionary DICT = ElementDictionary.getStandardElementDictionary();
        
        int[] TYPE2_TAGS = {
            Tag.ContentDate,
            Tag.ContentTime
    };


//      new 一個attribute(dicom的描述資訊)   
        Attributes fileMetadata = new Attributes();
        fileMetadata.setString(Tag.StudyInstanceUID, VR.UI, UIDUtils.createUID());
        fileMetadata.setString(Tag.SeriesInstanceUID, VR.UI, UIDUtils.createUID());
        fileMetadata.setString(Tag.SOPInstanceUID, VR.UI, UIDUtils.createUID());

//       =====插入資訊=====
        
        // patient info
        setMetadata(fileMetadata, Tag.PatientName, "Test Patient");
        setMetadata(fileMetadata, Tag.PatientID, "11311313");
        setMetadata(fileMetadata, Tag.PatientSex, "M");
        setMetadata(fileMetadata, Tag.PatientAge, "26Y");
        setMetadata(fileMetadata, Tag.PatientBirthDate, "19500101");

        // study info
        setMetadata(fileMetadata, Tag.StudyDate, "20240920");
        setMetadata(fileMetadata, Tag.StudyTime, "0:00:00");
        setMetadata(fileMetadata, Tag.StudyDescription, "Study Description");
        setMetadata(fileMetadata, Tag.StudyID, "123");
        setMetadata(fileMetadata, Tag.SOPClassUID, UID.SecondaryCaptureImageStorage);
        supplementType2Tags(fileMetadata);
        fileMetadata.setInt(Tag.NumberOfFrames, VR.IS, 1);
        fileMetadata.setInt(Tag.SeriesNumber, VR.IS, 2);

//       =====插入資訊結束=====

        
        Path imagePath= Paths.get("C:\\Users\\kris\\Downloads\\dcm\\test.jpg");
        Path dicomPath= Paths.get("C:\\Users\\kris\\Downloads\\dcm\\ttest.dcm");

        fileMetadata.trimToSize();
        
//      印出完整的Attribute   
        System.out.println(fileMetadata);

                
//      寫出dicom   
        try (SeekableByteChannel channel = Files.newByteChannel(imagePath);
             DicomOutputStream dos = new DicomOutputStream(dicomPath.toFile())) {

            XPEGParser parser = new JPEGParser(channel);
            parser.getAttributes(fileMetadata);

            dos.writeDataset(fileMetadata.createFileMetaInformation(parser.getTransferSyntaxUID()), fileMetadata);
            dos.writeHeader(Tag.PixelData, VR.OB, -1);
            dos.writeHeader(Tag.Item, null, 0);
            
//          這是single-frame dicom的寫法,如果要寫成multi-frame dicom,
//          需要重複執行copyPixelData function即可,不過要注意每張圖片的大小都要一樣 
//          如以下範例,多執行一次copyPixelData function(輸入不同的SeekableByteChannel) 即可合成multi-frame dicom 
//          copyPixelData(channel1, parser.getCodeStreamPosition(), dos);

            
            copyPixelData(channel, parser.getCodeStreamPosition(), dos);
            dos.writeHeader(Tag.SequenceDelimitationItem, null, 0);
            System.out.println("converted");
        }
        

    }

    public static void copyPixelData(SeekableByteChannel channel, long position, DicomOutputStream dos, byte... prefix)
            throws IOException {
        long codeStreamSize = channel.size() - position + prefix.length;
        dos.writeHeader(Tag.Item, null, (int) ((codeStreamSize + 1) & ~1));
        dos.write(prefix);
        channel.position(position);
        copy(channel, dos);
        if ((codeStreamSize & 1) != 0)
            dos.write(0);
    }

    private static void copy(ByteChannel in, OutputStream out) throws IOException {
        ByteBuffer bb = ByteBuffer.wrap(buf);
        int read;
        while ((read = in.read(bb)) > 0) {
            out.write(buf, 0, read);
            bb.clear();
        }
    }
    public static void setMetadata(Attributes metadata, int tag, String value) {

        if (value != null)
            metadata.setString(tag, DICT.vrOf(tag), value);
    }
    private static void supplementType2Tags(Attributes metadata) {
        for (int tag : TYPE2_TAGS)
            if (!metadata.contains(tag))
                metadata.setNull(tag, DICT.vrOf(tag));
    }

執行main function後就可以生成dicom檔案了!

以上是關於如何用圖片(jpg)合成出dicom檔的教學文章,希望對大家有幫助!!!


上一篇
Day 12 [數位醫療] 快速取出Multi-frame Dicom內的圖片
下一篇
Day 14 [數位醫療] 容器魔術師 --萬物皆可dockerize
系列文
數位醫療與雲原生第一次的親密接觸30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言